using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Configuration;
using CommandLine;

namespace CmdEmail
{
    internal sealed class Program
    {

        private sealed class Options
        {
            [Option("t", "to",
                    Required = true,
                    HelpText = "Recipient (To)")]
            public string to = String.Empty;

            [Option("f", "from",
                    Required = true,
                    HelpText = "Sender (From)")]
            public string from = String.Empty;

            [Option("b", "body",
                    Required = true,
                    HelpText = "Email Body (string or full path to filename)")]
            public string body = String.Empty;

            [Option("s", "subject",
                    Required = true,
                    HelpText = "Email Subject")]
            public string subject = String.Empty;

            [Option("a", "attach",
                    HelpText = "File Attach (multiple attachments seperated by comma)")]
            public string attach = String.Empty;

            [Option("h", "host",
                    HelpText = "SMTP Server - Optional only if provided in app config")]
            public string host = String.Empty;

            [Option("p", "port",
                    HelpText = "SMTP Port - Optional, can also be provided in app config")]
            public int port = 25;

            [Option("u", "username",
                    HelpText = "Username - Optional, can also be provided in app config")]
            public string username = String.Empty;

            [Option("p", "password",
                    HelpText = "Password - Optional, can also be provided in app config")]
            public string password = String.Empty;

            [Option("l", "logging",
                    HelpText = "Logging - (boolean) Optional, can also be provided in app config")]
            public string logging = String.Empty;

            [ValueList(typeof(List<string>))]
            public IList<string> DefinitionFiles = null;

            [HelpOption]
            public string GetUsage()
            {
                HelpText info = new HelpText("CmdEmail");
                info.Copyright = new CopyrightInfo("Don Kitchen", DateTime.Now.Year);
                info.AddLicenseLine("This is free software. You may redistribute copies of it under the terms of");
                info.AddLicenseLine("the MIT License <http://www.opensource.org/licenses/mit-license.php>.");
                info.AddUsageLine("Usage: CmdEmail -f a@b.com -t you@domain.com -s Subject -b Body");                
                info.AddUsageLine("       CmdEmail -f \"a@b.com\" -t \"you@domain.com\" -s \"Subject\" -b \"Body\"");
                info.AddUsageLine("       CmdEmail -f a@b.com -t you@domain.com,me@domain.com -s Subject -b Body");
                info.AddOptions(this);
                return info;
            }
        }

        static void Main(string[] args)
        {
            bool has_error = false;
            Options options = new Options();

            if (Parser.ParseArguments(args, options, Console.Out))
            {

                if (options.host.Length == 0)
                {
                    options.host = ConfigurationManager.AppSettings["SmtpServer"];
                    
                    if (options.host.Length == 0)
                    {
                        Console.WriteLine("SMTP Server must be provided as a switch or in the application configuration.");
                        Environment.Exit(1);
                    }
                }

                if (options.username.Length == 0)
                {
                    options.username = ConfigurationManager.AppSettings["UserName"];
                }

                if (options.password.Length == 0)
                {
                    options.password = ConfigurationManager.AppSettings["Password"];
                }

                if (options.logging.Length == 0)
                {
                    options.logging = ConfigurationManager.AppSettings["Logging"];
                }

                if (options.port == 0)
                {
                    options.port = Convert.ToInt32(ConfigurationManager.AppSettings["Port"]);
                }

                MailMessage message = new MailMessage();

                message.From = new MailAddress(@options.from);
                message.To.Add(@options.to);
                message.Subject = @options.subject;

                if (System.IO.File.Exists(options.body))
                {
                    System.IO.TextReader tr = new System.IO.StreamReader(options.body);
                    message.Body = tr.ReadToEnd();
                    tr.Close();
                }
                else
                {
                    message.Body = @options.body;
                }

                // Add file attach to message
                if (!string.IsNullOrEmpty(options.attach))
                {
                    try
                    {
                        if (options.attach.IndexOf(",") != -1)
                        {
                            string[] atts = options.attach.Split(new char[] { ',' });
                            foreach (string att in atts)
                            {
                                message.Attachments.Add(new Attachment(att));
                                Console.WriteLine(att);
                            }
                        }
                        else
                        {
                            message.Attachments.Add(new Attachment(options.attach));
                        }
                    }
                    catch (Exception ex)
                    {
                        has_error = true;
                        // Write error and send message without attach
                        Console.WriteLine(ex.Message);
                    }
                }

                SmtpClient smtp = new SmtpClient();

                smtp.Host = options.host;
                smtp.Port = options.port;

                // Only use network credentials if a username was provided
                if ((options.username != null) && (options.username.Length > 0))
                {
                    System.Net.NetworkCredential networkCredential = new System.Net.NetworkCredential();
                    networkCredential.UserName = options.username;
                    networkCredential.Password = options.password;
                    smtp.Credentials = networkCredential;
                }

                // Log event to Event Log
                if (!string.IsNullOrEmpty(options.logging))
                {
                    if (options.logging.ToUpper() == "TRUE")
                    {
                        string str_log = options.from + Environment.NewLine;
                        str_log += options.to + Environment.NewLine;
                        str_log += options.subject;
                        if (!string.IsNullOrEmpty(options.attach)) str_log += Environment.NewLine + options.attach;
                        log(str_log);
                    }
                }

                // Don't send if there was an error
                if (has_error == true)
                {
                    Environment.Exit(1);
                }
                
                try
                {
                    smtp.Send(message);                    
                }
                catch (System.Exception ex)
                {
                    has_error = true;
                    Console.WriteLine(ex.Message.ToString());
                    Console.Write(ex.InnerException.ToString());
                }

                Environment.Exit(0);
            }
            else
            {
                Environment.Exit(1);
            }
        }

        static void log(string str_in)
        {
            try
            {
                System.Diagnostics.EventLog evlog = new System.Diagnostics.EventLog("Application");
                evlog.Source = "CmdEmail";
                evlog.WriteEntry(str_in, System.Diagnostics.EventLogEntryType.Information);
            }
            catch (Exception ex)
            {
                // Write error for not being able to log
                Console.WriteLine(ex.Message);
            }

        }
    }
}
